
# lasso
'''
Lasso是一种正则化线性回归方法，与Ridge回归类似，它通过正则化约束系数使其接近于0，
但Lasso使用的是L1正则化。这种正则化的一个特点是，它会导致一些系数精确地变为0，
意味着这些特征在模型中被完全忽略，从而实现了特征选择的效果。这不仅简化了模型，使其更易于解释，还突出了最重要的特征。
'''

import mglearn
import numpy as np
from matplotlib import pyplot as plt
from sklearn.linear_model import Lasso, Ridge
from sklearn.model_selection import train_test_split

X, y = mglearn.datasets.load_extended_boston()
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
lasso = Lasso().fit(X_train, y_train)
print("Training set score: {:.2f}".format(lasso.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lasso.score(X_test, y_test)))
print("Number of features used: {}".format(np.sum(lasso.coef_ != 0)))

# Training set score: 0.29
# Test set score: 0.21
# Number of features used: 4

'''
Lasso模型在训练集和测试集上表现不佳，显示出欠拟合的迹象，因为它只使用了105个特征中的4个。
和Ridge模型一样，Lasso模型也有一个正则化参数alpha，用来控制系数接近0的程度。
之前使用的是默认的alpha值1.0。为了减少欠拟合，我们可以尝试降低alpha值。
同时，为了使模型能够更好地拟合数据，我们还需要增加max_iter的值，即模型在达到收敛前的最大迭代次数。

0.01 100000
'''

lasso001 = Lasso(alpha=0.01,max_iter=100000).fit(X_train, y_train)
print("Training set score: {:.2f}".format(lasso001.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lasso001.score(X_test, y_test)))
print("Number of features used: {}".format(np.sum(lasso001.coef_ != 0)))
# Training set score: 0.90
# Test set score: 0.77
# Number of features used: 33

'''
减小alpha值允许Lasso模型拟合一个更复杂的模型，从而提高在训练集和测试集上的性能。
与Ridge模型相比，Lasso的性能略有提升，并且只选择了33个相关特征，使得模型更易于理解。
但如果alpha值设置得过低，就会削弱正则化效果，可能导致过拟合，最终得到的结果会类似于没有正则化的线性回归模型。

'''

lasso00001 = Lasso(alpha=0.0001,max_iter=100000).fit(X_train, y_train)
print("Training set score: {:.2f}".format(lasso00001.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lasso00001.score(X_test, y_test)))
print("Number of features used: {}".format(np.sum(lasso00001.coef_ != 0)))
# Training set score: 0.95
# Test set score: 0.64
# Number of features used: 96

ridge01 = Ridge(alpha=0.1).fit(X_train, y_train)

# 再次对不同模型的系数进行作图
plt.plot(lasso.coef_,'s',label="Lasso alpha=1")
plt.plot(lasso001.coef_,'^',label="Lasso alpha=0.01")
plt.plot(lasso00001.coef_,'v',label="Lasso alpha=0.0001")

plt.plot(ridge01.coef_,'o',label="Ridge alpha=0.1")
plt.legend(ncol=2,loc=(0,1.05))
plt.ylim(-25,25)
plt.xlabel("Coefficient index")
plt.ylabel("Coefficient magnitude")
# plt.show()

'''
当alpha值较大（如1）时，Lasso模型的大多数系数变为0，剩下的也很小。
减小alpha到0.01时，更多特征的系数变为0，形成一个向上的三角形。
当alpha进一步减小到0.0001时，模型正则化效果很弱，大部分系数都不为0且较大。
相比之下，Ridge模型在alpha=0.1时的预测性能与Lasso在alpha=0.01时相似，
但Ridge的所有系数都不为0。

在实际应用中，通常优先选择Ridge回归，特别是当特征数量众多且认为只有少数几个重要时，
Lasso可能更合适，因为它通过将一些系数设为0来实现特征选择，使得模型更易于解释。
scikit-learn提供的ElasticNet类结合了Lasso和Ridge的正则化，
虽然效果好，但需要调整两个正则化参数，分别对应L1和L2正则化。

'''
